Introduction
The distributions of annual peak flows at USGS streamgages are used estimate flood frequency-magnitude characteristics at gaged sites by use of the log-Peason type-III distribution. This distribution is described by measures of the mean, variance, and skewness of the logarithm of annual peak flows. Estimates of high magnitude floods are particularly sensitive to the skewness of the distribution, although skewness estimates based on data from an individual streamgage are highly variable. Based on guidelines provided in Bulletin 17B and 17C, a regional estimate of flood skew is combined with an at-site (station skew) estimate to help stabilize the estimate of flood frequency characteristics.
A Bayesian generalized least squares (B-GLS) model is the standard approach for estimating the regional skew by regression on basin and climatic characteristics. This approach accounts for the length of record and spatial correlations among contemporaneous annual peaks in a network of streamgages by appropriately adjusting model parameters and uncertainty estimates. Despite the capabilities of the underlying model, identifying individual basin or climatic characteristics that are statistically associated with flood skew is problematic. Therefore, a constant is commonly used to estimate regional skew under the B-GLS model.
It may be the case, however, that subtle spatial variations in regional skew are caused by a combination of factors that are not linearly associated with available basin or climatic characteristics. Such effects may result in a persistent spatial pattern in the residuals of the skew estimates. To assess this possibility, a generalized additive model (GAM) is applied to the skew residuals from a B-GLS analysis of two, two-digit hydrologic regions, which includes US Great Lakes (04) and the Ohio River (05) basins. The GAM model provides a flexible basis of smoothing functions to accommodate irregular variations in covariates, such as spatial coordinates of gaged basin centroids. Linear components also are accommodated in a GAM model.
Computed station skew statistics from 368 streamgages in hydrologic unit regions 04 and 05 with 35 or more years of annual peak flow data were used in this analysis. Station skews were computed by use of methods described in Bulletin 17C. A preliminary analysis of the data describes the spatial distribution of gaged basin centroids, and analyzes the distribution of station skew values for outliers. A GAM model was fit to the skew values using the eastings and northing of basin centroids to provide an initial assessment of the potential utility of the GAM model. Within the GAM analysis, station-skews for individual streamgages will be weighted by their record length. This preliminary assessment was followed by repeated, random partitioning of the data set into training and testing subsets containing 80- and 20-percent of the full data set, respectively. The testing data set was used to determine whether the GAM model outperformed the constant estimated by use of the B-GLS model.
Initialize Environment
library(tidyverse)
[30m-- [1mAttaching packages[22m --------------------------------------- tidyverse 1.2.0 --[39m
[30m[32mv[30m [34mggplot2[30m 2.2.1 [32mv[30m [34mpurrr [30m 0.2.4
[32mv[30m [34mtibble [30m 1.3.4 [32mv[30m [34mdplyr [30m 0.7.4
[32mv[30m [34mtidyr [30m 0.7.2 [32mv[30m [34mstringr[30m 1.2.0
[32mv[30m [34mreadr [30m 1.1.1 [32mv[30m [34mforcats[30m 0.2.0[39m
[30m-- [1mConflicts[22m ------------------------------------------ tidyverse_conflicts() --
[31mx[30m [34mdplyr[30m::[32mfilter()[30m masks [34mstats[30m::filter()
[31mx[30m [34mdplyr[30m::[32mlag()[30m masks [34mstats[30m::lag()[39m
library(knitr)
Read in Skew Data for HUC Regions 04 and 05
df <- read_tsv(file = 'C:/Home/SW_Specialist/Skew0405/data/skew_data.txt') %>%
mutate(Station = paste0('0',USGS),
Resid_skew_sign = factor(sign(Residuals))) %>%
rename(Record_len = Pseudo_Length,
Station_skew = Station_Skew,
Residual_skew = Residuals)
Parsed with column specification:
cols(
Index = col_integer(),
USGS = col_integer(),
Pseudo_Length = col_integer(),
Station_Skew = col_double(),
log10_DA = col_double(),
Lat_Cntrd = col_double(),
Long_Cntrd = col_double(),
Residuals = col_double()
)
List Subset of Data and Summarize
kable(df[1:20,c('Station','Station_skew','Residual_skew','Lat_Cntrd','Long_Cntrd')],
caption = 'Sample of Skew Residual Data')
| 03336645 |
0.419 |
0.332 |
40.39385 |
-88.00935 |
| 03336900 |
0.000 |
-0.086 |
40.25089 |
-88.07321 |
| 03343400 |
-0.736 |
-0.822 |
39.92401 |
-88.14127 |
| 03344500 |
0.102 |
0.016 |
39.34818 |
-88.00714 |
| 03345500 |
-0.827 |
-0.913 |
39.51656 |
-88.13700 |
| 03346000 |
-0.304 |
-0.390 |
39.26853 |
-87.91700 |
| 03378000 |
-0.456 |
-0.542 |
38.53839 |
-87.94023 |
| 03378635 |
0.334 |
0.248 |
39.30351 |
-88.52165 |
| 03379500 |
-0.599 |
-0.686 |
38.99769 |
-88.48511 |
| 03380500 |
-0.037 |
-0.123 |
38.56331 |
-88.72489 |
| 03381500 |
0.239 |
0.153 |
38.64497 |
-88.44497 |
| 03382100 |
1.739 |
1.653 |
37.61436 |
-88.85263 |
| 03384450 |
-0.355 |
-0.441 |
37.53137 |
-88.52718 |
| 03385000 |
-0.231 |
-0.317 |
37.47848 |
-88.61897 |
| 03274650 |
-1.257 |
-1.343 |
40.04106 |
-85.10903 |
| 03275000 |
-0.360 |
-0.446 |
39.84952 |
-85.09757 |
| 03275600 |
-0.210 |
-0.297 |
39.86655 |
-84.84453 |
| 03276700 |
0.518 |
0.431 |
39.08198 |
-85.11773 |
| 03277000 |
0.076 |
-0.010 |
39.13191 |
-85.21422 |
| 03291780 |
-0.639 |
-0.725 |
38.93353 |
-85.28100 |
Plot Distribution of Streamgage Centrois
Note: symbols discretize residuals into positive and negative values
us_map %>%
filter(region %in% c('michigan', 'ohio', 'indiana', 'wisconsin', 'illinois',
'pennsylvania','new york', 'kentucky', 'west virginia',
'vermont')) %>%
ggplot( aes(x = long, y = lat, group = group)) +
geom_polygon(fill = 'tan', color = 'black') +
geom_polygon(data = huc2_0405, aes(x = long, y = lat, group = group),
fill = NA, color = 'blue') +
geom_point( data = df, aes( x = Long_Cntrd, y = Lat_Cntrd, group = NULL),
color = 'red') +
coord_map('conic', lat0 = 42)
Regions defined for each Polygons

Project Latitudes and Longitudes of Basin Centroids
library(rgdal)
library(sp)
df_prj <- df
coordinates(df_prj) <- c('Long_Cntrd', 'Lat_Cntrd')
class(df_prj)
[1] "SpatialPointsDataFrame"
attr(,"package")
[1] "sp"
proj4string(df_prj) <- "+proj=longlat +datum=NAD83"
# Same transform as
# EPSG:102003 USA_Contiguous_Albers_Equal_Area_Conic'
proj_sel <- 'EPSG:102004 USA_Contiguous_Lambert_Conformal_Conic'
# EPSG:102005 USA_Contiguous_Equidistant_Conic
df_prj <- spTransform(df_prj, CRS = CRS("+init=esri:102004"))
easting <- attributes(df_prj)$coords[,1]
northing <- attributes(df_prj)$coords[,2]
plot(easting, northing, pch = 16, col = 'blue')

east_std <- (easting - mean(easting ))/100000
nrth_std <- (northing - mean(northing))/100000
plot(east_std, nrth_std, pch = 16, col = 'green4',
main = paste('Regional Skew Streamgages',proj_sel),
xlab = 'Standardized Easting', ylab = 'Standardized Northing')

df %>%
ggplot( aes( x = Station_skew)) +
geom_histogram() +
geom_vline( xintercept = 0, color = 'red', linetype = 'dashed')

ndxOut <- which(df$Station_skew > 2)
# Remove outlier
df <- df[-ndxOut,]
df %>%
ggplot( aes( x = Station_skew)) +
geom_freqpoly( aes(y = ..density..), color = 'salmon', size = 1.2) +
geom_vline( xintercept = 0, color = 'red', linetype = 'dashed') +
stat_function(fun = dnorm, args = list(mean = mean(df$Station_skew),
sd = sd(df$Station_skew)),
color = 'blue') +
theme_few()

library(mgcv)
df$east <- east_std[-ndxOut]
df$nrth <- nrth_std[-ndxOut]
gam1 <- gam(Station_skew ~ s(east, nrth), weights = Record_len, data = df)
summary(gam1)
Family: gaussian
Link function: identity
Formula:
Station_skew ~ s(east, nrth)
Parametric coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 0.07062 0.02185 3.231 0.00135 **
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Approximate significance of smooth terms:
edf Ref.df F p-value
s(east,nrth) 24.42 27.72 3.847 7.74e-10 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
R-sq.(adj) = 0.215 Deviance explained = 26.8%
GCV = 12.151 Scale est. = 11.307 n = 366
plot(gam1)

df$gam_resid <- gam1$residuals
df %>%
ggplot( aes(x = gam_resid) ) +
geom_density(colour = 'red', size = 1.5) +
geom_density( aes(x = Residual_skew), color = 'blue', size = 1.5) +
theme_few()

us_map %>%
filter(region %in% c('michigan', 'ohio', 'indiana', 'wisconsin', 'illinois',
'pennsylvania','new york', 'kentucky', 'west virginia',
'vermont')) %>%
ggplot( aes(x = long, y = lat, group = group)) +
geom_polygon(fill = 'tan', color = 'black') +
coord_map('conic', lat0 = 42) +
# theme_void() + # This eliminates lat/lon marks
# theme_few() +
geom_point(data = df, aes( x=Long_Cntrd, y = Lat_Cntrd,
colour = gam_resid, group = NULL)) +
scale_colour_gradient2(low = "red" , mid = "white",
high = "blue" )

Skew Contour Map
A skew contour map is developed that is based on the gam1 model above.
plot_ly( x = c(xvec), y = c(yvec),
z = matrix(zvec,40,40, byrow = TRUE), type = 'contour',
contours = list(start = -0.5, end = 0.7, size = 0.2, showlabels = TRUE)) %>%
add_trace(type = 'scatter', mode = 'markers', x = df$east, y = df$nrth,
color = 'red', hovertext = paste(df$Station, df$Station_skew))
'scatter' objects don't have these attributes: 'z', 'contours'
Valid attributes include:
'type', 'visible', 'showlegend', 'legendgroup', 'opacity', 'name', 'uid', 'ids', 'customdata', 'hoverinfo', 'hoverlabel', 'stream', 'x', 'x0', 'dx', 'y', 'y0', 'dy', 'text', 'hovertext', 'mode', 'hoveron', 'line', 'connectgaps', 'cliponaxis', 'fill', 'fillcolor', 'marker', 'textposition', 'textfont', 'r', 't', 'error_y', 'error_x', 'xaxis', 'yaxis', 'xcalendar', 'ycalendar', 'idssrc', 'customdatasrc', 'hoverinfosrc', 'xsrc', 'ysrc', 'textsrc', 'hovertextsrc', 'textpositionsrc', 'rsrc', 'tsrc', 'key', 'set', 'frame', 'transforms', '_isNestedKey', '_isSimpleKey', '_isGraticule'
'scatter' objects don't have these attributes: 'z', 'contours'
Valid attributes include:
'type', 'visible', 'showlegend', 'legendgroup', 'opacity', 'name', 'uid', 'ids', 'customdata', 'hoverinfo', 'hoverlabel', 'stream', 'x', 'x0', 'dx', 'y', 'y0', 'dy', 'text', 'hovertext', 'mode', 'hoveron', 'line', 'connectgaps', 'cliponaxis', 'fill', 'fillcolor', 'marker', 'textposition', 'textfont', 'r', 't', 'error_y', 'error_x', 'xaxis', 'yaxis', 'xcalendar', 'ycalendar', 'idssrc', 'customdatasrc', 'hoverinfosrc', 'xsrc', 'ysrc', 'textsrc', 'hovertextsrc', 'textpositionsrc', 'rsrc', 'tsrc', 'key', 'set', 'frame', 'transforms', '_isNestedKey', '_isSimpleKey', '_isGraticule'
LS0tDQp0aXRsZTogIlByZWxpbWluYXJ5IEFuYWx5c2lzIG9mIFNrZXcgUmVzaWR1YWxzIGluIEhVQ3MgMDQgYW5kIDA1Ig0KYXV0aG9yOiBEYXZlIEhvbHRzY2hsYWcNCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQoNCiMjIEludHJvZHVjdGlvbg0KDQpUaGUgZGlzdHJpYnV0aW9ucyBvZiBhbm51YWwgcGVhayBmbG93cyBhdCBVU0dTIHN0cmVhbWdhZ2VzIGFyZSB1c2VkIGVzdGltYXRlIGZsb29kIGZyZXF1ZW5jeS1tYWduaXR1ZGUgY2hhcmFjdGVyaXN0aWNzIGF0IGdhZ2VkIHNpdGVzIGJ5IHVzZSBvZiB0aGUgbG9nLVBlYXNvbiB0eXBlLUlJSSBkaXN0cmlidXRpb24uICBUaGlzIGRpc3RyaWJ1dGlvbiBpcyBkZXNjcmliZWQgYnkgbWVhc3VyZXMgb2YgdGhlIG1lYW4sIHZhcmlhbmNlLCBhbmQgc2tld25lc3Mgb2YgdGhlIGxvZ2FyaXRobSBvZiBhbm51YWwgcGVhayBmbG93cy4gIEVzdGltYXRlcyBvZiBoaWdoIG1hZ25pdHVkZSBmbG9vZHMgYXJlIHBhcnRpY3VsYXJseSBzZW5zaXRpdmUgdG8gdGhlIHNrZXduZXNzIG9mIHRoZSBkaXN0cmlidXRpb24sIGFsdGhvdWdoIHNrZXduZXNzIGVzdGltYXRlcyBiYXNlZCBvbiBkYXRhIGZyb20gYW4gaW5kaXZpZHVhbCBzdHJlYW1nYWdlIGFyZSBoaWdobHkgdmFyaWFibGUuIEJhc2VkIG9uIGd1aWRlbGluZXMgcHJvdmlkZWQgaW4gQnVsbGV0aW4gMTdCIGFuZCAxN0MsIGEgcmVnaW9uYWwgZXN0aW1hdGUgb2YgZmxvb2Qgc2tldyBpcyBjb21iaW5lZCB3aXRoIGFuIGF0LXNpdGUgKHN0YXRpb24gc2tldykgZXN0aW1hdGUgdG8gaGVscCBzdGFiaWxpemUgdGhlIGVzdGltYXRlIG9mIGZsb29kIGZyZXF1ZW5jeSBjaGFyYWN0ZXJpc3RpY3MuICANCg0KQSBCYXllc2lhbiBnZW5lcmFsaXplZCBsZWFzdCBzcXVhcmVzIChCLUdMUykgbW9kZWwgaXMgdGhlIHN0YW5kYXJkIGFwcHJvYWNoIGZvciBlc3RpbWF0aW5nIHRoZSByZWdpb25hbCBza2V3IGJ5IHJlZ3Jlc3Npb24gb24gYmFzaW4gYW5kIGNsaW1hdGljIGNoYXJhY3RlcmlzdGljcy4gIFRoaXMgYXBwcm9hY2ggYWNjb3VudHMgZm9yIHRoZSBsZW5ndGggb2YgcmVjb3JkIGFuZCBzcGF0aWFsIGNvcnJlbGF0aW9ucyBhbW9uZyBjb250ZW1wb3JhbmVvdXMgYW5udWFsIHBlYWtzIGluIGEgbmV0d29yayBvZiBzdHJlYW1nYWdlcyBieSBhcHByb3ByaWF0ZWx5IGFkanVzdGluZyBtb2RlbCBwYXJhbWV0ZXJzIGFuZCB1bmNlcnRhaW50eSBlc3RpbWF0ZXMuIERlc3BpdGUgdGhlIGNhcGFiaWxpdGllcyBvZiB0aGUgdW5kZXJseWluZyBtb2RlbCwgaWRlbnRpZnlpbmcgaW5kaXZpZHVhbCBiYXNpbiBvciBjbGltYXRpYyBjaGFyYWN0ZXJpc3RpY3MgdGhhdCBhcmUgc3RhdGlzdGljYWxseSBhc3NvY2lhdGVkIHdpdGggZmxvb2Qgc2tldyBpcyBwcm9ibGVtYXRpYy4gIFRoZXJlZm9yZSwgYSBjb25zdGFudCBpcyBjb21tb25seSB1c2VkIHRvIGVzdGltYXRlIHJlZ2lvbmFsIHNrZXcgdW5kZXIgdGhlIEItR0xTIG1vZGVsLiAgDQoNCkl0IG1heSBiZSB0aGUgY2FzZSwgaG93ZXZlciwgdGhhdCBzdWJ0bGUgc3BhdGlhbCB2YXJpYXRpb25zIGluIHJlZ2lvbmFsIHNrZXcgYXJlIGNhdXNlZCBieSBhIGNvbWJpbmF0aW9uIG9mIGZhY3RvcnMgdGhhdCBhcmUgbm90IGxpbmVhcmx5IGFzc29jaWF0ZWQgd2l0aCBhdmFpbGFibGUgYmFzaW4gb3IgY2xpbWF0aWMgY2hhcmFjdGVyaXN0aWNzLiBTdWNoIGVmZmVjdHMgbWF5IHJlc3VsdCBpbiBhIHBlcnNpc3RlbnQgc3BhdGlhbCBwYXR0ZXJuIGluIHRoZSByZXNpZHVhbHMgb2YgdGhlIHNrZXcgZXN0aW1hdGVzLiAgVG8gYXNzZXNzIHRoaXMgcG9zc2liaWxpdHksIGEgZ2VuZXJhbGl6ZWQgYWRkaXRpdmUgbW9kZWwgKEdBTSkgaXMgYXBwbGllZCB0byB0aGUgc2tldyByZXNpZHVhbHMgZnJvbSBhIEItR0xTIGFuYWx5c2lzIG9mIHR3bywgdHdvLWRpZ2l0IGh5ZHJvbG9naWMgcmVnaW9ucywgd2hpY2ggaW5jbHVkZXMgVVMgR3JlYXQgTGFrZXMgKDA0KSBhbmQgdGhlIE9oaW8gUml2ZXIgKDA1KSBiYXNpbnMuIFRoZSBHQU0gbW9kZWwgcHJvdmlkZXMgYSBmbGV4aWJsZSBiYXNpcyBvZiBzbW9vdGhpbmcgZnVuY3Rpb25zIHRvIGFjY29tbW9kYXRlIGlycmVndWxhciB2YXJpYXRpb25zIGluIGNvdmFyaWF0ZXMsIHN1Y2ggYXMgc3BhdGlhbCBjb29yZGluYXRlcyBvZiBnYWdlZCBiYXNpbiBjZW50cm9pZHMuICBMaW5lYXIgY29tcG9uZW50cyBhbHNvIGFyZSBhY2NvbW1vZGF0ZWQgaW4gYSBHQU0gbW9kZWwuDQoNCkNvbXB1dGVkIHN0YXRpb24gc2tldyBzdGF0aXN0aWNzIGZyb20gMzY4IHN0cmVhbWdhZ2VzIGluIGh5ZHJvbG9naWMgdW5pdCByZWdpb25zIDA0IGFuZCAwNSB3aXRoIDM1IG9yIG1vcmUgeWVhcnMgb2YgYW5udWFsIHBlYWsgZmxvdyBkYXRhIHdlcmUgdXNlZCBpbiB0aGlzIGFuYWx5c2lzLiAgU3RhdGlvbiBza2V3cyB3ZXJlIGNvbXB1dGVkIGJ5IHVzZSBvZiBtZXRob2RzIGRlc2NyaWJlZCBpbiBCdWxsZXRpbiAxN0MuICBBIHByZWxpbWluYXJ5IGFuYWx5c2lzIG9mIHRoZSBkYXRhIGRlc2NyaWJlcyB0aGUgc3BhdGlhbCBkaXN0cmlidXRpb24gb2YgZ2FnZWQgYmFzaW4gY2VudHJvaWRzLCBhbmQgYW5hbHl6ZXMgdGhlIGRpc3RyaWJ1dGlvbiBvZiBzdGF0aW9uIHNrZXcgdmFsdWVzIGZvciBvdXRsaWVycy4gIEEgR0FNIG1vZGVsIHdhcyBmaXQgdG8gdGhlIHNrZXcgdmFsdWVzIHVzaW5nIHRoZSBlYXN0aW5ncyBhbmQgbm9ydGhpbmcgb2YgYmFzaW4gY2VudHJvaWRzIHRvIHByb3ZpZGUgYW4gaW5pdGlhbCBhc3Nlc3NtZW50IG9mIHRoZSBwb3RlbnRpYWwgdXRpbGl0eSBvZiB0aGUgR0FNIG1vZGVsLiBXaXRoaW4gdGhlIEdBTSBhbmFseXNpcywgc3RhdGlvbi1za2V3cyBmb3IgaW5kaXZpZHVhbCBzdHJlYW1nYWdlcyB3aWxsIGJlIHdlaWdodGVkIGJ5IHRoZWlyIHJlY29yZCBsZW5ndGguIFRoaXMgcHJlbGltaW5hcnkgYXNzZXNzbWVudCB3YXMgZm9sbG93ZWQgYnkgcmVwZWF0ZWQsIHJhbmRvbSBwYXJ0aXRpb25pbmcgb2YgdGhlIGRhdGEgc2V0IGludG8gdHJhaW5pbmcgYW5kIHRlc3Rpbmcgc3Vic2V0cyBjb250YWluaW5nIDgwLSBhbmQgMjAtcGVyY2VudCBvZiB0aGUgZnVsbCBkYXRhIHNldCwgcmVzcGVjdGl2ZWx5LiAgVGhlIHRlc3RpbmcgZGF0YSBzZXQgd2FzIHVzZWQgdG8gZGV0ZXJtaW5lIHdoZXRoZXIgdGhlIEdBTSBtb2RlbCBvdXRwZXJmb3JtZWQgdGhlIGNvbnN0YW50IGVzdGltYXRlZCBieSB1c2Ugb2YgdGhlIEItR0xTIG1vZGVsLiANCg0KIyMgSW5pdGlhbGl6ZSBFbnZpcm9ubWVudA0KDQpgYGB7ciBzZXR1cH0NCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeShnZ3RoZW1lcykNCmxpYnJhcnkoa25pdHIpDQpgYGANCioqKg0KDQojIyBSZWFkIGluIFNrZXcgRGF0YSBmb3IgSFVDIFJlZ2lvbnMgMDQgYW5kIDA1DQoNCmBgYHtyIHJlYWRfZGF0YX0NCmRmIDwtIHJlYWRfdHN2KGZpbGUgPSAnQzovSG9tZS9TV19TcGVjaWFsaXN0L1NrZXcwNDA1L2RhdGEvc2tld19kYXRhLnR4dCcpICU+JSANCiAgIG11dGF0ZShTdGF0aW9uID0gcGFzdGUwKCcwJyxVU0dTKSwNCiAgICAgICAgICBSZXNpZF9za2V3X3NpZ24gPSBmYWN0b3Ioc2lnbihSZXNpZHVhbHMpKSkgJT4lIA0KICAgcmVuYW1lKFJlY29yZF9sZW4gICAgICA9IFBzZXVkb19MZW5ndGgsDQogICAgICAgICAgU3RhdGlvbl9za2V3ICAgID0gU3RhdGlvbl9Ta2V3LA0KICAgICAgICAgIFJlc2lkdWFsX3NrZXcgICA9IFJlc2lkdWFscykgDQoNCmBgYA0KDQojIyBMaXN0IFN1YnNldCBvZiBEYXRhIGFuZCBTdW1tYXJpemUNCg0KYGBge3IgbGlzdF9kYXRhLCBmaWcuY2FwID0gJ1RhYmxlIHNob3dpbmcgY29udGVudHMgb2Ygc2tldyBkYXRhIHNldCd9DQoNCmthYmxlKGRmWzE6MjAsYygnU3RhdGlvbicsJ1N0YXRpb25fc2tldycsJ1Jlc2lkdWFsX3NrZXcnLCdMYXRfQ250cmQnLCdMb25nX0NudHJkJyldLA0KICAgICAgY2FwdGlvbiA9ICdTYW1wbGUgb2YgU2tldyBSZXNpZHVhbCBEYXRhJykNCg0KIyBQcmludCBzdW1tYXJ5IG9mIA0Kc3VtbWFyeShkZikNCg0KYGBgDQoNCiMjIFBsb3QgRGlzdHJpYnV0aW9uIG9mIFN0cmVhbWdhZ2UgQ2VudHJvaXMNCg0KTm90ZTogc3ltYm9scyBkaXNjcmV0aXplIHJlc2lkdWFscyBpbnRvIHBvc2l0aXZlIGFuZCBuZWdhdGl2ZSB2YWx1ZXMNCg0KYGBge3IgY29udmVydF9jb29yZH0NCmxpYnJhcnkocmdkYWwpDQpsaWJyYXJ5KHNwKQ0KDQpwYXRoIDwtICdDOi9Ib21lL1NXX1NwZWNpYWxpc3QvU2tldzA0MDUvR0lTL1dCRF8wNV9IVTJfU2hhcGUvU2hhcGUnIA0KaHVjMl9vaGlvX3JpdmVyICA8LSByZWFkT0dSKGRzbiA9IHBhdGgsIGxheWVyID0gIldCREhVMiIpDQoNCnBhdGggPC0gJ0M6L0hvbWUvU1dfU3BlY2lhbGlzdC9Ta2V3MDQwNS9HSVMvV0JEXzA0X0hVMl9TaGFwZS9TaGFwZScNCmh1YzJfZ3JlYXRfbGFrZXMgPC0gcmVhZE9HUihkc24gPSBwYXRoLCBsYXllciA9ICJXQkRIVTIiKSANCg0KaHVjMl8wNDA1ICAgICAgICA8LSByYmluZChodWMyX2dyZWF0X2xha2VzLCBodWMyX29oaW9fcml2ZXIpDQoNCiMgSG93IHRvIGV4dHJhY3QgZGF0YWZyYW1lIGZyb20gc3BhdGlhbCBwb2x5Z29uDQpzcHAgPC0gU3BhdGlhbFBvbHlnb25zRGF0YUZyYW1lKGh1YzJfMDQwNSwgZGF0YSA9IGFzLmRhdGEuZnJhbWUoSFVDMikpDQpkZnggPC0gZGF0YS5mcmFtZShpZCA9IGdldFNwUFBvbHlnb25zSURTbG90cyhodWMyXzA0MDUpKQ0Kcm93Lm5hbWVzKGRmeCkgPC0gZ2V0U3BQUG9seWdvbnNJRFNsb3RzKGh1YzJfMDQwNSkNCnNwZGYgPC0gU3BhdGlhbFBvbHlnb25zRGF0YUZyYW1lKGh1YzJfMDQwNSwgZGF0YSA9ZGZ4KQ0KDQpodWMyXzA0MDUgJT4lIA0KICAgZ2dwbG90KCBhZXMoeCA9IGxvbmcsIHkgPSBsYXQsIGdyb3VwID0gZ3JvdXApKSArDQogICBnZW9tX3BvbHlnb24oZmlsbCA9IGNvbG9ycygpWzE4XSwgY29sb3IgPSAiYmxhY2siKSArDQogICBnZW9tX3BvaW50KGRmLCBhZXMoeCA9IExvbmdfQ250cmQsIHkgPSBMYXRfQ250cmQpKQ0KDQoNCiAgIGdlb21fcG9seWdvbihodWMyX29oaW9fcml2ZXIsIGFlcyh4ID0gbG9uZywgeSA9IGxhdCwgZ3JvdXAgPSBncm91cCksDQogICAgICAgICAgICAgICAgZmlsbCA9IGNvbG9ycygpWzE1XSwgY29sb3IgPSAncmVkJykNCg0KDQpmaWxsID0gY29sb3JzKClbMThdLCANCisgDQogICANCiAgIGdlb21fcG9seWdvbihkYXRhID0gc3RhdGVzX29oaW9fcml2ZXIsIA0KICAgICAgICAgICAgICAgIGFlcyh4ID0gbG9uZywgeSA9IGxhdCwgZ3JvdXAgPSBncm91cCksDQogICAgICAgICAgICAgICAgZmlsbCA9IE5BLCBjb2xvciA9ICdncmV5JykgKw0KICAgZ2VvbV9wb2ludChkYXRhID0gc2tld19zaXRlcywgDQogICAgICAgICAgICAgIGFlcyggeCA9IExPTkdfQ0VOVCwgeSA9IExBVF9DRU5ULCBncm91cCA9IE5VTEwpLA0KICAgICAgICAgICAgICBjb2xvciA9ICdyZWQnLCANCiAgICAgICAgICAgICAgc2l6ZSAgPSAwLjUpICsNCiAgIGNvb3JkX21hcCgpICsNCiAgIHRoZW1lX2ZldygpICsgeGxhYignTG9uZ2l0dWRlJykgKyB5bGFiKCdMYXRpdHVkZScpIA0KDQoNCg0KDQp1c19tYXAgPC0gbWFwX2RhdGEoJ3N0YXRlJykNCg0KdXNfbWFwICU+JSANCiAgIGZpbHRlcihyZWdpb24gJWluJSBjKCdtaWNoaWdhbicsICdvaGlvJywgJ2luZGlhbmEnLCAnd2lzY29uc2luJywgJ2lsbGlub2lzJywNCiAgICAgICAgICAgICAgICAgICAgICAgICdwZW5uc3lsdmFuaWEnLCduZXcgeW9yaycsICdrZW50dWNreScsICd3ZXN0IHZpcmdpbmlhJywNCiAgICAgICAgICAgICAgICAgICAgICAgICd2ZXJtb250JykpICU+JSANCiAgIGdncGxvdCggYWVzKHggPSBsb25nLCB5ID0gbGF0LCBncm91cCA9IGdyb3VwKSkgKyANCiAgIGdlb21fcG9seWdvbihmaWxsID0gJ3RhbicsIGNvbG9yID0gJ2JsYWNrJykgKyANCiAgIGdlb21fcG9seWdvbihkYXRhID0gaHVjMl8wNDA1LCBhZXMoeCA9IGxvbmcsIHkgPSBsYXQsIGdyb3VwID0gZ3JvdXApLA0KICAgICAgICAgICAgICAgIGZpbGwgPSBOQSwgY29sb3IgPSAnYmx1ZScpICsNCiAgIGdlb21fcG9pbnQoICBkYXRhID0gZGYsIGFlcyggeCA9IExvbmdfQ250cmQsIHkgPSBMYXRfQ250cmQsIGdyb3VwID0gTlVMTCksIA0KICAgICAgICAgICAgICAgIGNvbG9yID0gJ3JlZCcpICsgDQogICBjb29yZF9tYXAoJ2NvbmljJywgbGF0MCA9IDQyKSArDQogICAjIHRoZW1lX3ZvaWQoKSArICMgVGhpcyBlbGltaW5hdGVzIGxhdC9sb24gbWFya3MgDQogICB0aGVtZV9mZXcoKSArDQogICBnZW9tX3BvaW50KGRhdGEgPSBkZiwgYWVzKCB4PUxvbmdfQ250cmQsIHkgPSBMYXRfQ250cmQsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb3VyID0gUmVzaWRfc2tld19zaWduLCBncm91cCA9IE5VTEwpKSArDQogICBzY2FsZV9jb2xvdXJfbWFudWFsKCB2YWx1ZXMgPSBjKCdyZWQnLCAnYmx1ZScpKQ0KDQoNCmBgYA0KKioqDQojIyBQcm9qZWN0IExhdGl0dWRlcyBhbmQgTG9uZ2l0dWRlcyBvZiBCYXNpbiBDZW50cm9pZHMNCg0KYGBge3IgcHJval9sYXRfbG9uZ30NCmxpYnJhcnkocmdkYWwpDQpsaWJyYXJ5KHNwKQ0KDQpkZl9wcmogIDwtIGRmDQoNCmNvb3JkaW5hdGVzKGRmX3ByaikgPC0gYygnTG9uZ19DbnRyZCcsICdMYXRfQ250cmQnKQ0KY2xhc3MoZGZfcHJqKQ0KDQpwcm9qNHN0cmluZyhkZl9wcmopIDwtICIrcHJvaj1sb25nbGF0ICtkYXR1bT1OQUQ4MyINCg0KIyBTYW1lIHRyYW5zZm9ybSBhcyANCiMgIEVQU0c6MTAyMDAzIFVTQV9Db250aWd1b3VzX0FsYmVyc19FcXVhbF9BcmVhX0NvbmljJw0KcHJval9zZWwgPC0gICdFUFNHOjEwMjAwNCBVU0FfQ29udGlndW91c19MYW1iZXJ0X0NvbmZvcm1hbF9Db25pYycNCiMgIEVQU0c6MTAyMDA1IFVTQV9Db250aWd1b3VzX0VxdWlkaXN0YW50X0NvbmljDQpkZl9wcmogPC0gc3BUcmFuc2Zvcm0oZGZfcHJqLCBDUlMgPSBDUlMoIitpbml0PWVzcmk6MTAyMDA0IikpDQoNCmVhc3RpbmcgIDwtIGF0dHJpYnV0ZXMoZGZfcHJqKSRjb29yZHNbLDFdDQpub3J0aGluZyA8LSBhdHRyaWJ1dGVzKGRmX3ByaikkY29vcmRzWywyXQ0KDQoNCnBsb3QoZWFzdGluZywgbm9ydGhpbmcsIHBjaCA9IDE2LCBjb2wgPSAnYmx1ZScpDQoNCmVhc3Rfc3RkIDwtIChlYXN0aW5nICAtIG1lYW4oZWFzdGluZyApKS8xMDAwMDANCm5ydGhfc3RkIDwtIChub3J0aGluZyAtIG1lYW4obm9ydGhpbmcpKS8xMDAwMDANCg0KcGxvdChlYXN0X3N0ZCwgbnJ0aF9zdGQsIHBjaCA9IDE2LCBjb2wgPSAnZ3JlZW40JywNCiAgICAgbWFpbiA9IHBhc3RlKCdSZWdpb25hbCBTa2V3IFN0cmVhbWdhZ2VzJyxwcm9qX3NlbCksDQogICAgIHhsYWIgPSAnU3RhbmRhcmRpemVkIEVhc3RpbmcnLCB5bGFiID0gJ1N0YW5kYXJkaXplZCBOb3J0aGluZycpDQoNCmBgYA0KYGBge3Igc2tld19kaXN0fQ0KDQpkZiAlPiUNCiAgIGdncGxvdCggYWVzKCB4ID0gU3RhdGlvbl9za2V3KSkgKw0KICAgZ2VvbV9oaXN0b2dyYW0oKSArIA0KICAgZ2VvbV92bGluZSggeGludGVyY2VwdCA9IDAsIGNvbG9yID0gJ3JlZCcsIGxpbmV0eXBlID0gJ2Rhc2hlZCcpDQoNCm5keE91dCA8LSB3aGljaChkZiRTdGF0aW9uX3NrZXcgPiAyKQ0KDQojIFJlbW92ZSBvdXRsaWVyDQoNCmRmIDwtIGRmWy1uZHhPdXQsXQ0KDQoNCmRmICU+JQ0KICAgZ2dwbG90KCBhZXMoIHggPSBTdGF0aW9uX3NrZXcpKSArDQogICBnZW9tX2ZyZXFwb2x5KCBhZXMoeSA9IC4uZGVuc2l0eS4uKSwgY29sb3IgPSAnc2FsbW9uJywgc2l6ZSA9IDEuMikgKyANCiAgIGdlb21fdmxpbmUoIHhpbnRlcmNlcHQgPSAwLCBjb2xvciA9ICdyZWQnLCBsaW5ldHlwZSA9ICdkYXNoZWQnKSArDQogICBzdGF0X2Z1bmN0aW9uKGZ1biA9IGRub3JtLCBhcmdzID0gbGlzdChtZWFuID0gbWVhbihkZiRTdGF0aW9uX3NrZXcpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2QgICA9ICAgc2QoZGYkU3RhdGlvbl9za2V3KSksDQogICAgICAgICAgICAgICAgIGNvbG9yID0gJ2JsdWUnKSArDQogICB0aGVtZV9mZXcoKQ0KDQpgYGANCg0KDQpgYGB7ciBnYW1fYW5hbH0NCg0KbGlicmFyeShtZ2N2KQ0KDQpkZiRlYXN0IDwtIGVhc3Rfc3RkWy1uZHhPdXRdDQpkZiRucnRoIDwtIG5ydGhfc3RkWy1uZHhPdXRdDQoNCg0KZ2FtMSA8LSBnYW0oU3RhdGlvbl9za2V3IH4gcyhlYXN0LCBucnRoKSwgd2VpZ2h0cyA9IFJlY29yZF9sZW4sIGRhdGEgPSBkZikNCg0Kc3VtbWFyeShnYW0xKQ0KDQpwbG90KGdhbTEpDQoNCmRmJGdhbV9yZXNpZCA8LSBnYW0xJHJlc2lkdWFscw0KDQpgYGANCg0KDQoNCmBgYHtyIHJlc2lkX3Bsb3R9DQoNCmRmICU+JSANCiAgIGdncGxvdCggYWVzKHggPSBnYW1fcmVzaWQpICkgKw0KICAgZ2VvbV9kZW5zaXR5KGNvbG91ciA9ICdyZWQnLCBzaXplID0gMS41KSArDQogICBnZW9tX2RlbnNpdHkoIGFlcyh4ID0gUmVzaWR1YWxfc2tldyksIGNvbG9yID0gJ2JsdWUnLCBzaXplID0gMS41KSArDQogICB0aGVtZV9mZXcoKSANCg0KdXNfbWFwICU+JSANCiAgIGZpbHRlcihyZWdpb24gJWluJSBjKCdtaWNoaWdhbicsICdvaGlvJywgJ2luZGlhbmEnLCAnd2lzY29uc2luJywgJ2lsbGlub2lzJywNCiAgICAgICAgICAgICAgICAgICAgICAgICdwZW5uc3lsdmFuaWEnLCduZXcgeW9yaycsICdrZW50dWNreScsICd3ZXN0IHZpcmdpbmlhJywNCiAgICAgICAgICAgICAgICAgICAgICAgICd2ZXJtb250JykpICU+JSANCiAgIGdncGxvdCggYWVzKHggPSBsb25nLCB5ID0gbGF0LCBncm91cCA9IGdyb3VwKSkgKyANCiAgIGdlb21fcG9seWdvbihmaWxsID0gJ3RhbicsIGNvbG9yID0gJ2JsYWNrJykgKyANCiAgIGNvb3JkX21hcCgnY29uaWMnLCBsYXQwID0gNDIpICsNCiAgICMgdGhlbWVfdm9pZCgpICsgIyBUaGlzIGVsaW1pbmF0ZXMgbGF0L2xvbiBtYXJrcyANCiAgICMgdGhlbWVfZmV3KCkgKw0KICAgZ2VvbV9wb2ludChkYXRhID0gZGYsIGFlcyggeD1Mb25nX0NudHJkLCB5ID0gTGF0X0NudHJkLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG91ciA9IGdhbV9yZXNpZCwgZ3JvdXAgPSBOVUxMKSkgKw0KICAgc2NhbGVfY29sb3VyX2dyYWRpZW50Mihsb3cgID0gInJlZCIgLCBtaWQgPSAid2hpdGUiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICBoaWdoID0gImJsdWUiICkNCg0KDQpgYGANCg0KIyMgU2tldyBDb250b3VyIE1hcA0KDQpBIHNrZXcgY29udG91ciBtYXAgaXMgZGV2ZWxvcGVkIHRoYXQgaXMgYmFzZWQgb24gdGhlIGdhbTEgbW9kZWwgYWJvdmUuICANCg0KYGBge3IgY29udG91cl9pbmZvfQ0KDQp0bXAgIDwtIHBsb3QoZ2FtMSkNCg0KDQp4dmVjIDwtIHRtcFtbMV1dJHgNCnl2ZWMgPC0gdG1wW1sxXV0keQ0KenZlYyA8LSB0bXBbWzFdXSRmaXQNCg0KcGxvdF9seSggeCA9IGMoeHZlYyksIHkgPSBjKHl2ZWMpLA0KICAgeiA9IG1hdHJpeCh6dmVjLDQwLDQwLCBieXJvdyA9IFRSVUUpLCB0eXBlID0gJ2NvbnRvdXInLCANCiAgIGNvbnRvdXJzID0gbGlzdChzdGFydCA9IC0wLjUsIGVuZCA9IDAuNywgc2l6ZSA9IDAuMiwgc2hvd2xhYmVscyA9IFRSVUUpKSAlPiUgDQogICBhZGRfdHJhY2UodHlwZSA9ICdzY2F0dGVyJywgbW9kZSA9ICdtYXJrZXJzJywgeCA9IGRmJGVhc3QsIHkgPSBkZiRucnRoLCANCiAgICAgICAgICAgICAgIGNvbG9yID0gJ3JlZCcsIGhvdmVydGV4dCA9IHBhc3RlKGRmJFN0YXRpb24sIGRmJFN0YXRpb25fc2tldykpIA0KDQoNCg0KDQpgYGA=